package com.example.ribbon.rules;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author 莫磊
 * @date 2025/8/21
 * @description
 */
@Configuration
public class DeptRuleConfig {

    /**
     * 自定义负载均衡
     * @param supplier 服务实例供应器，可以拿到注册中心中某个服务的所有可用实例
     * @return
     */
    @Bean
    public ReactorServiceInstanceLoadBalancer ribbonRule(ServiceInstanceListSupplier supplier) {
        return new DeptRule("DETP1-SERVICE", supplier);
    }

    class DeptRule implements ReactorServiceInstanceLoadBalancer {

        private final String serviceId;
        private final ServiceInstanceListSupplier supplier;
        private int count = 0;
        private int index = 0;

        public DeptRule(String serviceId, ServiceInstanceListSupplier supplier) {
            this.serviceId = serviceId;
            this.supplier = supplier;
        }

        @Override
        public Mono<Response<ServiceInstance>> choose(Request request) {
            // 自定义的规则实现
            return supplier.get().next().map(instances -> {
                if (instances.isEmpty()) {
                    return new EmptyResponse();
                }
                if (count <= index) {
                    count ++;
                } else {
                    index ++;
                    count = 0;
                }

                if (index == instances.size()) {
                    index = 0;
                }

                // Eureka / Nacos 返回服务实例时，并没有保证顺序。
                // 有时是按注册时间，有时是按心跳刷新顺序。所以这里不一定会根据算法获取想要的结果
                ServiceInstance serviceInstance = instances.get(index);
                System.out.println(serviceInstance.getInstanceId());
                return new DefaultResponse(serviceInstance);
            });
        }
    }

}
